package paper

import (
	"data/config"
	"data/view/common"
	"data/view/question"
	"data/view/user"
	"fmt"
	"public/message"
	"public/mycache"
	"public/mylog"
	"public/mysqldb"
	"public/tools"
	"strings"
	"time"

	"github.com/ant0ine/go-json-rest/rest"
	qrcode "github.com/skip2/go-qrcode"
)

/*
	出卷
*/
func CreatePaper(w rest.ResponseWriter, r *rest.Request) {
	var req CreatePaperParam
	tools.GetRequestJsonObj(r, &req)

	//参数检测
	if !tools.CheckParam(req.Access_token, req.Name, req.Subject) || len(req.Questions) == 0 {
		w.WriteJson(message.GetErrorMsg(message.ParameterInvalid, req))
		return
	}
	//验证token，并获取用户名
	username, _, bfind := user.GetUserFromToken(req.Access_token)
	if !bfind {
		w.WriteJson(message.GetErrorMsg(message.TokenFailure))
		return
	}
	var db mysqldb.MySqlDB
	defer db.OnDestoryDB()
	orm := db.OnGetDBOrm(config.GetDbUrl())

	var questions []string
	var paper Examination_tbl
	for _, v := range req.Questions {
		t := strings.Split(v, ":")
		var tmp question.Question_tbl
		orm.Where("quest_no = ? and is_vaild = ?", t[0], 1).Find(&tmp)
		if tmp.Id > 0 {
			questions = append(questions, v)
		}
	}
	paper_no := common.CreateUnique(common.RECRUIT_TOPIC + "paper")
	paper.Name = req.Name
	paper.Topic = common.RECRUIT_TOPIC
	paper.Bundle = req.Subject
	paper.Pid = paper_no //试卷编号
	paper.Operator = username
	paper.Limit_time = req.Limit_time
	paper.Attach = req.Attach
	paper.Questions = fmt.Sprintf("%s", questions[0])
	for i := 1; i < len(questions); i++ {
		paper.Questions += common.SPLIT + fmt.Sprintf("%s", questions[i])
	}
	paper.Pass_score = req.Pass_score
	paper.Exam_url = ""
	paper.Create_time = time.Now()
	err := orm.Create(&paper).Error
	if err != nil {
		w.WriteJson(message.GetErrorMsg(message.UnknownError))
		return
	}
	msg := message.GetSuccessMsg(message.NormalMessageId)
	msg.Data = paper_no
	w.WriteJson(msg)
}

/*
	编辑试卷
*/
func UpdatePaper(w rest.ResponseWriter, r *rest.Request) {
	var req UpdatePaperParam
	tools.GetRequestJsonObj(r, &req)

	//参数检测
	if !tools.CheckParam(req.Access_token, req.Paper_no) {
		w.WriteJson(message.GetErrorMsg(message.ParameterInvalid, req))
		return
	}
	//验证token，并获取用户名
	username, _, bfind := user.GetUserFromToken(req.Access_token)
	if !bfind {
		w.WriteJson(message.GetErrorMsg(message.TokenFailure))
		return
	}
	var db mysqldb.MySqlDB
	defer db.OnDestoryDB()
	orm := db.OnGetDBOrm(config.GetDbUrl())

	var questions []string
	for _, v := range req.Questions {
		t := strings.Split(v, ":")
		var tmp question.Question_tbl
		orm.Where("quest_no = ? and is_vaild = ?", t[0], 1).Find(&tmp)
		if tmp.Id > 0 {
			questions = append(questions, v)
		}
	}
	var paper Examination_tbl
	paper.Name = req.Name
	paper.Bundle = req.Subject
	if len(questions) > 0 {
		paper.Questions = fmt.Sprintf("%s", questions[0])
		for i := 1; i < len(questions); i++ {
			paper.Questions += common.SPLIT + fmt.Sprintf("%s", questions[i])
		}
	}
	paper.Operator = username
	paper.Limit_time = req.Limit_time
	paper.Is_vaild = req.Is_vaild
	paper.Attach = req.Attach
	paper.Pass_score = req.Pass_score
	err := orm.Table("examination_tbl").Where("pid = ?", req.Paper_no).Updates(&paper).Error
	if err != nil {
		w.WriteJson(message.GetErrorMsg(message.UnknownError))
		return
	}
	msg := message.GetSuccessMsg(message.NormalMessageId)
	msg.Data = req.Paper_no
	w.WriteJson(msg)
}

/*
	获取全部试卷
*/
func GetAllPaper(w rest.ResponseWriter, r *rest.Request) {
	var req GetAllPaperParam
	tools.GetRequestJsonObj(r, &req)

	//参数检测
	if !tools.CheckParam(req.Access_token) {
		w.WriteJson(message.GetErrorMsg(message.ParameterInvalid, req))
		return
	}
	//验证token，并获取用户名
	_, _, bfind := user.GetUserFromToken(req.Access_token)
	if !bfind {
		w.WriteJson(message.GetErrorMsg(message.TokenFailure))
		return
	}
	var db mysqldb.MySqlDB
	defer db.OnDestoryDB()
	orm := db.OnGetDBOrm(config.GetDbUrl())

	var papers []Examination_tbl
	var result []PaperSimpleInfo
	orm.Find(&papers)
	if len(papers) > 0 {
		for _, v := range papers {
			var tmp PaperSimpleInfo
			tmp.Attach = v.Attach
			tmp.Bundle = v.Bundle
			tmp.Is_vaild = v.Is_vaild
			tmp.Limit_time = v.Limit_time
			tmp.Name = v.Name
			tmp.Operator = v.Operator
			tmp.Paper_no = v.Pid
			//试卷题目
			qs, score_sum := GetPaperQuestions(v.Questions)
			tmp.Questions = qs
			tmp.Topic = v.Topic
			tmp.Exam_url = v.Exam_url
			tmp.Pass_score = v.Pass_score
			tmp.Sum_score = score_sum
			tmp.Questions_count = len(qs)
			tmp.Create_time = v.Create_time
			result = append(result, tmp)
		}
	}
	msg := message.GetSuccessMsg(message.NormalMessageId)
	msg.Data = result
	w.WriteJson(msg)

}

/*
	获取试卷详情
*/
func GetPaperDetail(w rest.ResponseWriter, r *rest.Request) {
	var req GetPaperDetailParam
	tools.GetRequestJsonObj(r, &req)

	//参数检测
	if !tools.CheckParam(req.Access_token, req.Paper_no) {
		w.WriteJson(message.GetErrorMsg(message.ParameterInvalid, req))
		return
	}
	//验证token，并获取用户名
	_, _, bfind := user.GetUserFromToken(req.Access_token)
	if !bfind {
		w.WriteJson(message.GetErrorMsg(message.TokenFailure))
		return
	}
	var db mysqldb.MySqlDB
	defer db.OnDestoryDB()
	orm := db.OnGetDBOrm(config.GetDbUrl())
	var paper Examination_tbl
	var result PaperAllInfo
	orm.Where("pid = ?", req.Paper_no).Find(&paper)
	if paper.Id > 0 {
		result.Attach = paper.Attach
		result.Bundle = paper.Bundle
		result.Is_vaild = paper.Is_vaild
		result.Limit_time = paper.Limit_time
		result.Name = paper.Name
		result.Operator = paper.Operator
		result.Paper_no = paper.Pid
		qs, score_sum := GetPaperQuestions(paper.Questions)
		result.Questions = getMultiQuestionByPaper(req.Paper_no, qs, orm)
		result.Topic = paper.Topic
		result.Exam_url = paper.Exam_url
		result.Pass_score = paper.Pass_score
		result.Sum_score = score_sum
		result.Create_time = paper.Create_time
		result.Questions_count = len(qs)
	}
	msg := message.GetSuccessMsg(message.NormalMessageId)
	msg.Data = result
	w.WriteJson(msg)

}

/*
	交卷
*/
func Submit(w rest.ResponseWriter, r *rest.Request) {
	var req SubmitParam
	tools.GetRequestJsonObj(r, &req)

	//参数检测
	if !tools.CheckParam(req.Access_token, req.Paper_no, req.Teacher) || len(req.User_answer) == 0 {
		w.WriteJson(message.GetErrorMsg(message.ParameterInvalid, req))
		return
	}
	//验证token，并获取用户名
	username, _, bfind := user.GetUserFromToken(req.Access_token)
	if !bfind {
		w.WriteJson(message.GetErrorMsg(message.TokenFailure))
		return
	}
	var db mysqldb.MySqlDB
	defer db.OnDestoryDB()
	orm := db.OnGetDBOrm(config.GetDbUrl())

	var paper Examination_tbl
	orm.Where("pid = ?", req.Paper_no).Find(&paper)
	if paper.Id == 0 {
		w.WriteJson(message.GetErrorMsg(message.NotFindError))
		return
	}
	_, score_mp := GetPaperQsScore(req.Paper_no)
	for _, v := range req.User_answer {
		var info question.Question_tbl
		orm.Where("quest_no = ?", v.Quest_no).Find(&info)
		if info.Id > 0 && info.Is_vaild == 0 {
			var tmp Exam_detail_tbl
			tmp.Answerer = username
			tmp.Paper_no = req.Paper_no
			tmp.Quest_no = v.Quest_no
			tmp.Test_time = time.Now()
			tmp.Examiner = req.Teacher
			if len(v.Answer) > 0 {
				tmp.Answer = fmt.Sprintf("%s", v.Answer[0])
				for i := 1; i < len(v.Answer); i++ {
					tmp.Answer += common.SPLIT + fmt.Sprintf("%s", v.Answer[i])
				}
				if info.Bundle == common.SCHOICE_TYPE_C || info.Bundle == common.CHECK_TYPE_C { //单选题or判断题
					if v.Answer[0] == info.Answer {
						tmp.Score = score_mp[v.Quest_no]
					}
				}
				if info.Bundle == common.MCHOICE_TYPE_C { //多选题
					tmp.Score, _ = judgeMchoiceScore(v.Answer, strings.Split(info.Answer, common.SPLIT), score_mp[v.Quest_no])
				}
			}
			err := orm.Create(&tmp).Error
			if err != nil {
				w.WriteJson(message.GetErrorMsg(message.UnknownError))
				return
			}
		}
	}
	w.WriteJson(message.GetSuccessMsg(message.NormalMessageId))
}

/*
	查看某一试卷答题情况
*/
func GetUserAnswer(w rest.ResponseWriter, r *rest.Request) {
	var req GetPaperDetailParam
	tools.GetRequestJsonObj(r, &req)

	//参数检测
	if !tools.CheckParam(req.Access_token, req.Paper_no) {
		w.WriteJson(message.GetErrorMsg(message.ParameterInvalid, req))
		return
	}
	//验证token，并获取用户名
	username, _, bfind := user.GetUserFromToken(req.Access_token)
	if !bfind {
		w.WriteJson(message.GetErrorMsg(message.TokenFailure))
		return
	}
	var db mysqldb.MySqlDB
	defer db.OnDestoryDB()
	orm := db.OnGetDBOrm(config.GetDbUrl())

	var paper Examination_tbl
	orm.Where("pid = ?", req.Paper_no).Find(&paper)
	if paper.Id == 0 {
		w.WriteJson(message.GetErrorMsg(message.NotFindError))
		return
	}
	_, paper_sum_score := GetPaperQuestions(paper.Questions) //试卷满分
	_, score_mp := GetPaperQsScore(req.Paper_no)             //每题满分
	// paper_sum_score := GetPaperSumScore(paper.Questions)
	var result []UserAnswer

	answerers, _ := GetPaperAnswerer(req.Paper_no) //应考考生
	if len(answerers) > 0 {
		for _, v := range answerers {
			var tmp UserAnswer
			var qus []UserAnswerDetail
			var views []Exam_question_view

			var scan_sum Scan_sum
			orm.Raw("select sum(score) as sum FROM exam_detail_tbl WHERE answerer = ? and paper_no = ? and examiner = ?",
				v.Answerer, req.Paper_no, username).Scan(&scan_sum)

			orm.Table("exam_detail_tbl as d").Select("d.*,d.answer as user_answer,q.*").
				Joins("join question_tbl as q on d.quest_no = q.quest_no").
				Where("d.answerer = ? and d.paper_no = ? and d.examiner = ?", v.Answerer, req.Paper_no, username).Scan(&views)
			for _, v := range views {
				var t UserAnswerDetail
				t.Answer = strings.Split(v.Answer, common.SPLIT) //正确答案
				t.Answer_time = v.Answer_time                    //答题耗时
				t.Attach = v.Attach
				t.Bundle = v.Bundle
				t.Content = v.Content
				t.Exam_time = v.Exam_time           //阅卷时间
				t.Examiner = v.Examiner             //阅卷人
				t.Full_score = score_mp[v.Quest_no] //满分值
				t.Is_vaild = v.Is_vaild
				t.Limit_time = v.Limit_time //答题限时
				t.Operator = v.Operator     //出题人
				t.Options = strings.Split(v.Option, common.SPLIT)
				t.Picture = strings.Split(v.Picture, common.SPLIT)
				t.Pid = v.Pid
				t.Quest_no = v.Quest_no
				t.Score = v.Score         //得分
				t.Test_time = v.Test_time //答题时间
				t.Title = v.Title
				t.Topic = v.Topic
				t.User_answer = strings.Split(v.User_answer, common.SPLIT)
				t.Difficulty = v.Difficulty //难度
				t.Analysis = v.Analysis     //题目解析
				qus = append(qus, t)
			}
			tmp.User = v.Answerer
			tmp.User_answer = qus
			tmp.Sum_score = scan_sum.Sum          //总得分
			tmp.Paper_sum_score = paper_sum_score //试卷满分
			tmp.Pass_score = paper.Pass_score     //及格分
			result = append(result, tmp)
		}
	}
	msg := message.GetSuccessMsg(message.NormalMessageId)
	msg.Data = result
	w.WriteJson(msg)
}

/*
	评分
*/
func JudgeScore(w rest.ResponseWriter, r *rest.Request) {
	var req JudgeScoreParam
	tools.GetRequestJsonObj(r, &req)

	//参数检测
	if !tools.CheckParam(req.Access_token, req.Paper_no, req.User) || len(req.Quest_score) == 0 {
		w.WriteJson(message.GetErrorMsg(message.ParameterInvalid, req))
		return
	}
	//验证token，并获取用户名
	username, _, bfind := user.GetUserFromToken(req.Access_token)
	if !bfind {
		w.WriteJson(message.GetErrorMsg(message.TokenFailure))
		return
	}
	var db mysqldb.MySqlDB
	defer db.OnDestoryDB()
	orm := db.OnGetDBOrm(config.GetDbUrl())
	//判断是否答题
	var exam []Exam_detail_tbl
	orm.Where("answerer = ? and paper_no = ? and examiner = ?", req.User, req.Paper_no, username).Find(&exam)
	if len(exam) == 0 {
		w.WriteJson(message.GetErrorMsg(message.NotFindError, "未答题"))
		return
	}
	for _, v := range req.Quest_score {

		u := map[string]interface{}{"score": v.Score, "examiner": username, "exam_time": time.Now()}
		err := orm.Table("exam_detail_tbl").Where("answerer = ? and paper_no = ? and quest_no = ? and examiner = ?",
			req.User, req.Paper_no, v.Quest_no, username).Updates(u).Error
		if err != nil {
			w.WriteJson(message.GetErrorMsg(message.UnknownError))
			return
		}
	}
	if len(req.Remark) > 0 {
		var remark Exam_remark_tbl
		remark.Paper_no = req.Paper_no
		remark.Answerer = req.User
		remark.Remark = req.Remark
		remark.Commentator = username
		remark.Remark_time = time.Now()
		remark.Attach = req.Attach
		err := orm.Create(&remark).Error
		if err != nil {
			w.WriteJson(message.GetErrorMsg(message.UnknownError))
			return
		}
	}
	var scan_sum Scan_sum
	orm.Raw("select sum(score) as sum FROM exam_detail_tbl WHERE answerer = ? and paper_no = ?",
		req.User, req.Paper_no).Scan(&scan_sum)
	msg := message.GetSuccessMsg(message.NormalMessageId)
	msg.Data = scan_sum.Sum //试卷总分
	w.WriteJson(msg)
}

/*
	查看答卷
*/
func GetScore(w rest.ResponseWriter, r *rest.Request) {
	var req GetPaperDetailParam
	tools.GetRequestJsonObj(r, &req)

	//参数检测
	if !tools.CheckParam(req.Access_token, req.Paper_no) {
		w.WriteJson(message.GetErrorMsg(message.ParameterInvalid, req))
		return
	}
	//验证token，并获取用户名
	username, _, bfind := user.GetUserFromToken(req.Access_token)
	if !bfind {
		w.WriteJson(message.GetErrorMsg(message.TokenFailure))
		return
	}
	var db mysqldb.MySqlDB
	defer db.OnDestoryDB()
	orm := db.OnGetDBOrm(config.GetDbUrl())

	var paper Examination_tbl
	orm.Where("pid = ?", req.Paper_no).Find(&paper)
	if paper.Id == 0 {
		w.WriteJson(message.GetErrorMsg(message.NotFindError))
		return
	}
	_, paper_sum_score := GetPaperQuestions(paper.Questions) //试卷满分
	_, score_mp := GetPaperQsScore(req.Paper_no)             //每题满分

	var views []Exam_question_view
	var tmp UserAnswer
	var qus []UserAnswerDetail
	var scan_sum Scan_sum
	var remark Exam_remark_tbl

	orm.Raw("select sum(score) as sum FROM exam_detail_tbl WHERE answerer = ? and paper_no = ?",
		username, req.Paper_no).Scan(&scan_sum)

	orm.Table("exam_detail_tbl as d").Select("d.*,d.answer as user_answer,q.*").
		Joins("join question_tbl as q on d.quest_no = q.quest_no").
		Where("d.answerer = ? and d.paper_no = ?", username, req.Paper_no).Scan(&views)

	orm.Where("paper_no = ? and answerer = ?", req.Paper_no, username).Find(&remark)
	for _, v := range views {
		var t UserAnswerDetail
		t.Answer = strings.Split(v.Answer, common.SPLIT) //正确答案
		t.Answer_time = v.Answer_time                    //答题耗时
		t.Attach = v.Attach
		t.Bundle = v.Bundle
		t.Content = v.Content
		t.Exam_time = v.Exam_time           //阅卷时间
		t.Examiner = v.Examiner             //阅卷人
		t.Full_score = score_mp[v.Quest_no] //满分值
		t.Is_vaild = v.Is_vaild
		t.Limit_time = v.Limit_time //答题限时
		t.Operator = v.Operator     //出题人
		t.Options = strings.Split(v.Option, common.SPLIT)
		t.Picture = strings.Split(v.Picture, common.SPLIT)
		t.Pid = v.Pid
		t.Quest_no = v.Quest_no
		t.Score = v.Score         //得分
		t.Test_time = v.Test_time //答题时间
		t.Title = v.Title
		t.Topic = v.Topic
		t.User_answer = strings.Split(v.User_answer, common.SPLIT)
		t.Difficulty = v.Difficulty //难度
		t.Analysis = v.Analysis     //题目解析
		qus = append(qus, t)
	}
	tmp.User = username
	tmp.User_answer = qus
	tmp.Sum_score = scan_sum.Sum          //总得分
	tmp.Paper_sum_score = paper_sum_score //试卷满分
	tmp.Pass_score = paper.Pass_score     //及格分
	tmp.Remark = remark.Remark            //评语
	tmp.Commentator = remark.Commentator  //评语人
	tmp.Remark_time = remark.Remark_time  //评语时间

	msg := message.GetSuccessMsg(message.NormalMessageId)
	msg.Data = tmp
	w.WriteJson(msg)
}

/*
	生成试卷二维码
*/
func GetQrcode(w rest.ResponseWriter, r *rest.Request) {
	var req GetPaperDetailParam
	tools.GetRequestJsonObj(r, &req)

	//参数检测
	if !tools.CheckParam(req.Access_token, req.Paper_no) {
		w.WriteJson(message.GetErrorMsg(message.ParameterInvalid, req))
		return
	}
	//验证token，并获取用户名
	username, _, bfind := user.GetUserFromToken(req.Access_token)
	if !bfind {
		w.WriteJson(message.GetErrorMsg(message.TokenFailure))
		return
	}
	var exam_qrcode string
	//从缓存中获取qrcode
	cache := mycache.OnGetCache("exam_qrcode")
	obj, b := cache.Value(req.Paper_no + username)
	if b {
		exam_qrcode = obj.(string)
	} else {
		//生成二维码
		var qrcode_url string = config.GetPaperQrcodeUrl() + "?paper_no=" + req.Paper_no + "&teacher=" + username

		err := qrcode.WriteFile(qrcode_url, qrcode.Medium, 256, tools.GetModelPath()+config.File_host+"/img/qrcode/"+req.Paper_no+username+".jpg")
		if err != nil {
			mylog.Error(err)
			w.WriteJson(message.GetErrorMsg(message.UnknownError))
			return
		}
		exam_qrcode = config.Url_host + config.File_host + "/img/qrcode/" + req.Paper_no + username + ".jpg"
		cache.Add(req.Paper_no+username, exam_qrcode, 24*time.Hour)
	}
	msg := message.GetSuccessMsg(message.NormalMessageId)
	msg.Data = exam_qrcode
	w.WriteJson(msg)
	return

}
